/*
 *INFO:
 *	This is the server part of the socket udp
 *	first is to get the handle of the UDP
 *Author:
 * 	Mark on 2014/3/30
 *	<mark199312@gmail.com>
 *
 */

/*
 *code log:
 *	2014/3/30
 *	add the struct fib *Fib and the struct 
 *
 */

#include"dispatch.h"
#include<time.h>
#include"ip_table.h"

extern struct buff_queue *Buffer_queue;
extern struct core_conf *Core_conf;
extern struct fib *Fib;
extern struct sockaddr_in *need_dispatched_client;
/*
 *init a socket from a address
 */

int init_addr_serv(struct node Node,struct sockaddr_in *addr_serv)
{
	int sock_fd=0;
	//get the handle of socket
	sock_fd = socket(AF_INET,SOCK_DGRAM,0);

	if(sock_fd < 0)
	{
        	perror("socket");
		log_error("socket fd init fail");
       		return;
	}
	else
	{
	        printf("sock sucessful\n");
		log_info("sock fd init successfully");
	}

	//init the server socket
	memset(addr_serv,0,sizeof(struct sockaddr_in));
	addr_serv->sin_family = AF_INET;
	addr_serv->sin_port = htons(Node.port);
	addr_serv->sin_addr.s_addr = htonl(INADDR_ANY);

	//bind the port of socket and handle

	if(bind(sock_fd,(struct sockaddr *)addr_serv,sizeof(struct sockaddr_in))<0 )
	{
        	perror("bind");
		log_error("socket fd bind fail");
        	return;
	}
	else
	{
        	printf("bind sucess\n");
		log_info("socket fd bind successfully");
	}
	
	return sock_fd;
}

/*
 *init a struct sockaddr_in by the struct node
 */

int init_addr_client(struct node Node,struct sockaddr_in *addr_serv)
{

	int sock_fd=0;
	//get the handle of socket
	sock_fd = socket(AF_INET,SOCK_DGRAM,0);

	if(sock_fd < 0)
	{
        	perror("socket");
		log_error("socket fd init fail");
       		return;
	}
	else
	{
	        printf("sock sucessful\n");
		log_info("sock fd init successfully");
	}

	//init the server socket
	memset(addr_serv,0,sizeof(struct sockaddr_in));

	addr_serv->sin_family = AF_INET;
	addr_serv->sin_port = htons(Node.port);

	addr_serv->sin_addr= Node.ip;
	
	return sock_fd;
}

/*
 *this is a thread to send the packet to client
 *accroding some logical problem
 */

#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
#endif

void * dispatch()
{
	int client_len;

	int recv_num;
	int send_num;
	
	client_len = sizeof(struct sockaddr_in);
	
	char recv_buf[20];

	bzero(recv_buf,sizeof(recv_buf));

	int sock_fd = Core_conf->sock_fd;
	
	while(1)
	{


#if DEBUG_SOCKET
                
		sendto(sock_fd,"dddddddddddd",7,0,(struct sockaddr *)need_dispatched_client,client_len);
        	
		recv_num = recvfrom(sock_fd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)need_dispatched_client,&client_len);

        	if(recv_num <  0)
        	{
                	printf("bad\n");
                	perror("again recvfrom");
                	exit(1);
        	}
        	else
        	{
        		recv_buf[recv_num]='\0';
  		      	printf("recv sucess:%s\n",recv_buf);
            		printf("receive from %s\n",inet_ntoa(need_dispatched_client->sin_addr));
        	}

#else

		//printf("now in the dispatch the packet number are      %d\n",buff_queue_count(Buffer_queue));		
	
		if(Buffer_queue->count>=0)
		{
	
			printf("start to send packet\n");
			

			struct buff_queue_node *bu_queue_node;
        		bu_queue_node=buff_queue_del(Buffer_queue);

			if(bu_queue_node==NULL)
			{
				log_error("count is 0 ,but del return NULL");
				continue;
			}
			
        		printf("begin send:\n");

			//first we should search in fib to find whether it exist 
			//if not we build a new item in fib
			//else we send the packet accroding to the fib
			
			struct sockaddr_in * need_send_client=NULL;

			need_send_client = Fib_find_hash(Fib,bu_queue_node->key);
		
			if(need_send_client == NULL)
			{
				log_info("has not find in fib about this item");
				need_send_client=need_dispatched_client;
				
				//new a fib and add to Fib
				struct fib *f=(struct fib*)malloc(sizeof(struct fib));
				
				f->key=*(bu_queue_node->key);
				f->node=need_send_client;
				f->start_time=time(NULL);
					
				Fib_add_hash(&Fib,f);
			}

			//in this we should add some to gurantee the balance is reliable and trust our fib


        		send_num = sendto(sock_fd,(void *)(bu_queue_node->packet),bu_queue_node->packet_len,0,(struct sockaddr *)need_send_client,client_len);
        		//send_num = sendto(sock_fd,"ddddddddddddddd",10,0,(struct sockaddr *)need_send_client,client_len);

        		if(send_num < 0)
       			{
	        		perror("sendto");
                		exit(1);
        		}
        		else
        		{
                		printf("send sucessful\n");
				printf("and the arrive time is: %d ",bu_queue_node->arrive_time);
				printf("the packet length is %d\n",bu_queue_node->packet_len);
        		}
		}
#endif
	}
	close(sock_fd);
	return;
}















